var DEFAULT_NUM_MAIN_COLS = 2;
var EDITABLE_CLASS = "editable";	// XXX: Is this class required? Is "droppable" more accurate?
var MAX_NUM_COLS = 3;

/* 
XXX: Rename cell to column
XXX: Make this more OO (using jquery plugins?)
*/

function enableEdit() {
	addEditableClass();
	decorateGrid();
}

function decorateGrid() {
	console.log("decorating");
	decorateRows();
	decorateCells();
	decorateAside();
	//insertPlaceholdersInAside();
	decorateAssets();
	decoratePlaceholders();
}

function disableEdit() {
	jQuery(".editable").removeClass(EDITABLE_CLASS);
	jQuery(".minibar").remove();
	// Remove the droppable functionality completely. This will return the element back to its pre-init state.
	jQuery(".ui-droppable").droppable("destroy");
}

function addEditableClass() {
	/* Change .row to .cms */
	jQuery(".row:not(:has(.editable))").addClass(EDITABLE_CLASS);
	jQuery(".asset:not(:has(.editable))").addClass(EDITABLE_CLASS);
	jQuery(".cell:not(:has(.editable))").addClass(EDITABLE_CLASS);
	jQuery(".placeholder:not(:has(.editable))").addClass(EDITABLE_CLASS);
}


/* DECORATOR FUNCTIONS ***************************************************/

/* Also insert placeholders if required */
function decorateRows() {
	// .row
	jQuery(layout4j.rowSelector + ":not(:has(.minibar))").each(function(index) {
		//var html = jQuery(this).html();
		//jQuery(this).html(rowMinibarHtml() + html);
		
		var me = jQuery(this);
		/* Children could be content or column elements. They're may be multiple child content elements. */
		var children = me.children(layout4j.columnSelector + ", " + layout4j.contentSelector);
		console.log("children", children);
		var numChildren = 0;
		for (var i = 0; (i < children.length); i++) {
			var width = $(children[i]).attr("cms-max-cols");
			if (width == undefined) {
				width = 1;
			}
			numChildren = numChildren + width;
		}
		console.log("numChildren", numChildren);
		me.prepend(rowMinibarHtml());
		
		/* Inherit max-cols from the closest ancestor that defines it */
		var ancestor = me.closest("div[cms-max-cols]"); /*.cell*/
		console.log("ancestor.length" + ancestor.length);
		var maxCols = 2; /* Default */
		if (ancestor.length > 0) {
			console.log("cms-max-cols", ancestor.attr("cms-max-cols"));
			if (ancestor.attr("cms-max-cols")) {
				maxCols = ancestor.attr("cms-max-cols");
			}
			console.log("maxCols: " + maxCols);
		}
		var numPlaceholdersToAdd = maxCols - numChildren;
		var row = me.closest(".row");
		for (i = 0; (i < numPlaceholdersToAdd); i++) {
			row.append(placeholderHtml(false));
		}
	});
}

function decorateCells() {
	jQuery(".cell:not(:has(.minibar))").each(function(index) {
		var column = jQuery(this);
		column.prepend(cellMinibarHtml());
	});
}
function decorateAside() {
	insertPlaceholdersInAside();
	/*
	jQuery(layout4j.asideSelector).each(function(index) {
		var aside = jQuery(this);
		aside.prepend(asideMinibarHtml());
	});
	*/
}

function insertPlaceholdersInAside() {
	var aside = jQuery(layout4j.asideSelector);
	if (typeof(aside) != "undefined") {
		var children = aside.find(layout4j.contentSelector + ", .placeholder");
		if (children) {
			//console.log("aside: numChildren " + children.length);
			if (children.length == 0) {
				aside.append(placeholderHtml(false));
			}
		}
	}
	console.log("leaving...");
}

function decorateAssets() {
	jQuery(layout4j.contentSelector + ":not(:has(.minibar))").each(function(index) {
		var me = jQuery(this);
		//var html = me.html();
		//me.html(assetMinibarHtml(me) + html);
		me.prepend(assetMinibarHtml(me));
		var styleId = me.attr("cms-style");
		me.find("select").val(styleId);
		
		var width = me.attr("cms-max-cols");
		var columnWidth = me.closest("div[cms-type='column']").attr("cms-max-cols");
		console.log("content width " + width + ", col width " + columnWidth);
		if (width < columnWidth) {
			console.log("HIT!");
			/* Append placeholder */
			me.closest("div[cms-type='row']").append(placeholderHtml(false));
		}
	});
}

function decoratePlaceholders() {
	jQuery(".placeholder:not(:has(.minibar))").each(function(index) {
		var html = jQuery(this).html();
		var showInsert = showPlaceholderInsert(jQuery(this));
		jQuery(this).html(placeholderMinibarHtml(showInsert) + html);
	});
}

/* HELPERS ***************************************************************/

/* @param hoverClassName Optional (default value is "active-drop-target") */
function initDroppable(hoverClassName) {
	if (hoverClassName == undefined) {
		hoverClassName = "active-drop-target";
	}
	jQuery(layout4j.contentSelector + ", .placeholder").droppable({
		drop: funcLoadAsset,
		hoverClass: "active-drop-target"
	});
}

/* @param peerEl an element that is a peer of the new placeholder */
// XXX: Rename showPlaceholderInsertIcon
function showPlaceholderInsert(peerEl) {
	var numPeers = 0;
	var siblings = jQuery(peerEl).siblings(layout4j.contentSelector + ",.placeholder");
	if (siblings) {
		// Add 1 for peerEl param, 1 for new placeholder
		numPeers = siblings.length + 1 + 1;
	}
	return (numPeers < MAX_NUM_COLS);
}

/* EVENTS ****************************************************************/

/* Expects param element to be inside a row */
function insertRowBelow(el) {
	var placeholdersHtml = "";
	for (i = 0; i < DEFAULT_NUM_MAIN_COLS; i++) {
		var showInsert = (i < MAX_NUM_COLS);
		placeholdersHtml = placeholdersHtml + placeholderHtml(showInsert);
	}
	jQuery(el).closest("div[cms-type='row']").after("<div class='row editable' cms-type='row'>" + rowMinibarHtml() + placeholdersHtml + "</div>");
}

function deleteRow(el) {
	if (jQuery("div[cms-type='row']").size() > 1) {
		jQuery(el).closest("div[cms-type='row']").remove();
	} else {
		alert("Sorry, there has to be a least one row");
	}
}

function deletePlaceholder(el) {
	jQuery(el).closest(".placeholder").remove();
}

/* Expects param element to be inside a placeholder */
function insertPlaceholderRight(el) {
	var placeholderEl = jQuery(el).closest(".placeholder");
	jQuery(el).closest("div[cms-type='row']").append(placeholderHtml(showPlaceholderInsert(placeholderEl)));
}

function deleteAsset(el) {
	var container = jQuery(el).closest(layout4j.columnSelector + ", " + layout4j.rowSelector);
	if (container.children(layout4j.contentSelector).size() > 1) {
		jQuery(el).closest(layout4j.contentSelector).remove();
	} else {
		/* XXX: Shouldn't give users option to delete it in the first place! */
		alert("Sorry, content can't be deleted when it has no siblings");
	}
}

/* Expects param element to be inside an asset */
function insertAssetBelow(el) {
	var asset = jQuery(el).closest(layout4j.contentSelector);
	if (asset) {
		if (!asset.parent().hasClass("column")) {
			// XXX: Should check existing asset for relevant colspan
			asset.wrap("<div class='column editable' cms-type='column'></div>");
			var cell = asset.closest(".column");
			cell.html(cellMinibarHtml() + cell.html() + placeholderHtml(false));
			/*cell.droppable({
				drop: funcLoadAsset
			});
			alert('1');*/
		} else {
			var cell = asset.closest(".column");
			cell.append(placeholderHtml(false));
		}
		/* Make relevant elements droppable */
		jQuery(layout4j.contentSelector + ", .placeholder").droppable({
			drop: funcLoadAsset
		});
		
	} else {
		alert("Cancelled - this operation only applies to content elements");
	}
}

function changeAssetTemplate(el) {
	/* Get details of new template to be displayed */
	var select = jQuery(el);
	var option = select.find("option:selected").first();
	var widthOfNewStyle = option.attr("style-width");
	var newStyle = option.attr("value");
	
	/* Get details of current content element */
	var assetEl = select.closest(layout4j.contentSelector);
	var widthOfCurrentStyle = assetEl.attr("cms-width");
	var assetId = assetEl.attr("cms-data-id");
	var assetType = assetEl.attr("cms-data-type");
	
	funcChangeAsset(assetEl, assetParams(assetId, assetType, newStyle));
	if ((widthOfNewStyle == 1) && (widthOfCurrentStyle == 2)) {
		/* Insert a placeholder to the right */
		select.closest(".row").append(placeholderHtml(false));
	} else if ((widthOfNewStyle == 2) && (widthOfCurrentStyle == 1)) {
		/* Remove placehodler to the right */
		select.closest(".row").find(".placeholder").remove();
	}
}

function assetParams(id, type, style) {
	var params = "styleId=" + style;
	if (id) params = params + "&dataId=" + id;
	if (type) params = params + "&dataTypeId=" + type;
	return params;
}

function deleteCell(el) {
	var cell = jQuery(el).closest(".cell");
	if (cell.children(".asset").size() > 1) {
		alert("Sorry, a column can't be deleted when it contains more than one asset");
	} else {
		cell.children(".minibar").remove();
		cell.children(".placeholder").remove();
		/* first() is just to be safe - there should only be one anyway */
		cell.children(".asset").first().unwrap();
	}
}

/* TEMPLATES *************************************************************/

function rowMinibarHtml() {
	return "<div class='minibar'>ROW <a href='#' onclick='insertRowBelow(this)' title='Insert row below'><span class='insert-below-icon' /></a> "
			+ "<a href='#' onclick='deleteRow(this)' title='Delete'><span class='delete-icon' /></a></div>";
}

function placeholderHtml(showInsert) {
	var showInsertFalse = false; 	/* Better to insert placeholders automatically */
	return "<div class='placeholder editable'>" + placeholderMinibarHtml(showInsertFalse) 
			+ "<!--Drop asset here-->&nbsp;</div>";
}

function placeholderMinibarHtml(showInsert) {
	var insertHtml = "";
	if (showInsert) {
		insertHtml = "<a href='#' onclick='insertPlaceholderRight(this)' title='Insert placeholder to the right'><span class='insert-right-icon' /></a> ";
	}
	/* No delete option for first placeholder in row? */
	return "<div class='minibar'>EMPTY " + insertHtml
			+ "<!--a href='#' onclick='deletePlaceholder(this)' title='Delete'><span class='delete-icon' /></a--></div>";
}

function assetMinibarHtml(assetEl) {
	var type = jQuery(assetEl).attr("cms-data-type");
	var styles = "";
	if (type != undefined) {
		if (type != undefined) {
			styles = jQuery("#cms-asset-type" + type).html();
		} else {
			styles = "No data type";
		}
	} else {
		styles = "No type";
	}
	return "<div class='minibar'>CONTENT <a href='#' onclick='insertAssetBelow(this)' title='Insert asset below'><span class='insert-below-icon' /></a> "
			+ "<a href='#' onclick='deleteAsset(this)' title='Delete'><span class='delete-icon' /></a>"
			+ styles + "</div>";
}

function cellMinibarHtml() {
	return "<div class='minibar'>COLUMN <a href='#' onclick='deleteCell(this)' title='Delete'><span class='delete-icon' /></a></div>";
}

function asideMinibarHtml() {
	return "<div class='minibar'>ASIDE</div>";
}

/* DROPPABLE *****************************************************************/

var funcLoadCallback = function(response, status, xhr) {
  	if (status == "error") {
	  	/* ??? */
	} else {
		var me = jQuery(this);
		me.children(".minibar").remove();	// Removes minibar
		var asset = me.children(layout4j.contentSelector);
		asset.unwrap();	// Removes parent
		enableEdit();
		asset.droppable({
			drop: funcLoadAsset
		});
	}
}

var funcLoadAsset = function (event, ui) {
	jQuery(this).children(".minibar").after("<div class='admin-message'>Loading...</div>");
	var params = ui.draggable.attr("cms-params");
	
	/* XXX: gContextPath is a global... urgh! */
	jQuery(this).load(layout4j.contentBaseUrl + params, funcLoadCallback);
}

var funcChangeAsset = function (targetElement, url) {
	var target = jQuery(targetElement);
	target.children(".minibar").after("<div class='admin-message'>Loading...</div>");
	
	/* XXX: gContextPath is a global... urgh! */
	target.load(layout4j.contentBaseUrl + url, funcLoadCallback);
}